import objects.triangle;
import pflanza.lsystem;
import pflanza.polygen;
import pflanza.tesselator;
import pflanza.brownterrain;
import pflanza.materials;
import pflanza.terrain;
import pflanza.plants;
import pflanza.plantdistributor;
import std.stdio;
import std.stream;
import path = std.path;
import std.file;
import srand = std.random;
import utils.configfile;
import utils.mover3;
import utils.vector3;
import utils.mt19937ar;
import utils.randval;

class Main {
    private {
        const outputDir = "pflanza_out/";
        char[] mInputPath;

        ConfigFile mCfg;
        Materials mMaterials;
        Terrain mTerrain;
        Plants mPlants;
        PlantDistributor mPlantDist;
    }

    this(char[][] args) {
        char[] cfgFilename;
        if (args.length > 1) {
            cfgFilename = args[1];
        } else {
            cfgFilename = "pflanza.cfg";
        }

        char[] curDir = getcwd();
        mInputPath = path.getDirName(cfgFilename) ~ path.sep;
        if (!path.isabs(mInputPath))
            mInputPath = curDir ~ path.sep ~ mInputPath;
        chdir(mInputPath);

        init_genrand(srand.rand());

        try {
            auto cfgFile = new File(cfgFilename,FileMode.In);
            mCfg = new ConfigFile(cfgFile,cfgFilename,null);
        } catch(Exception e) {
            writefln("Failed to read config file \"%s\"",cfgFilename);
            throw e;
        }
        mMaterials = new Materials();
        mMaterials.fromNode(mCfg.rootnode.getSubNode("materials",true));
        mTerrain = new Terrain();
        mTerrain.fromNode(mCfg.rootnode.getSubNode("terrain",true));
        mPlants = new Plants();
        mPlants.fromNode(mCfg.rootnode.getSubNode("plants",true));
        mPlantDist = new PlantDistributor(mPlants, mTerrain);
        mPlantDist.fromNode(mCfg.rootnode.getSubNode("distribution",true));
    }

    int exec() {
        auto scrFile = new File("pflanza.rs",FileMode.OutNew);
        scrFile.writefln("# Initialize");
        scrFile.writefln("clear");
        scrFile.writefln("loadidentity");
        scrFile.writefln();

        mMaterials.writeScript(scrFile);
        scrFile.writefln();

        writefln("Material definitions written");

        mTerrain.generate();
        mTerrain.save(outputDir ~ "pflanza_terrain.raw");
        mTerrain.writeScript(scrFile);
        scrFile.writefln();

        writefln("Terrain generated");

        mPlants.generate(outputDir);
        mPlants.writeScript(scrFile,outputDir);

        writefln("Plants generated");

        mPlantDist.generate();
        mPlantDist.writeScript(scrFile);

        writefln("Plants distributed in terrain");

        return 0;
    }
}

int main(char[][] args)
{
    init_genrand(345);

    auto m = new Main(args);
    return m.exec();
}
